package com.deng.api.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.deng.api.config.QiNiuUtil;
import com.deng.api.dto.UserDTO;
import com.deng.api.entity.AuthUser;
import com.deng.api.entity.SysRole;
import com.deng.api.entity.SysUser;
import com.deng.api.entity.SysUserRole;
import com.deng.api.mapper.SysUserMapper;
import com.deng.api.mapper.SysUserRoleMapper;
import com.deng.api.service.ISysUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.deng.api.vo.PageVO;
import com.deng.api.vo.UserPassVO;
import com.deng.commons.common.BaseResult;
import com.deng.commons.common.ErrorCode;
import com.deng.commons.utils.FileUtil;
import com.deng.commons.utils.UserUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统用户表 服务实现类
 * </p>
 *
 * @author deng
 * @since 2022-08-10
 */
@Service
@Slf4j
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private QiNiuUtil qiNiuUtil;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public AuthUser getUserByUserName(String username) {
        return sysUserMapper.getUserByUserName(username);
    }

    @Override
    public BaseResult modifyPassword(UserPassVO userPassVO) {
        AuthUser authUser = (AuthUser) UserUtils.getUser();
        //比较旧密码是否正确
        if(!passwordEncoder.matches(userPassVO.getOldPassword(),authUser.getPassword())){
            return BaseResult.fail(ErrorCode.CODE_1004);
        }
        SysUser user = new SysUser();
        user.setId(authUser.getId());
        user.setPassword(passwordEncoder.encode(userPassVO.getNewPassword()));
        if(sysUserMapper.updateById(user)>0){
            return BaseResult.success("修改成功");
        }
        return BaseResult.success("修改失败");
    }

    @Override
    public BaseResult uploadAvatar(MultipartFile multipartFile) {
        // 先判断文件格式对不对
        String image = "jpg png jpeg gif webp";
        String fileType = qiNiuUtil.getExc(multipartFile.getOriginalFilename());
        if (!StrUtil.isEmptyIfStr(fileType) && !image.contains(fileType)){
            return BaseResult.fail(ErrorCode.CODE_1005);
        }
        // 上传文件
        String url = qiNiuUtil.upload(multipartFile);
        if (StrUtil.isEmptyIfStr(url)){
            return BaseResult.fail();
        }
        //更新用户信息
        AuthUser authUser = (AuthUser) UserUtils.getUser();
        authUser.setAvatar(url);
        SysUser user = new SysUser();
        user.setId(authUser.getId());
        user.setAvatar(url);
        sysUserMapper.updateById(user);
        return BaseResult.success(url);
    }

    @Override
    public BaseResult getUsers(Integer page, Integer size, UserDTO userDTO) {
        //分页 -pageHelper的插件，mybatis-plus的page插件
        PageHelper.startPage(page+1,size);
        List<UserDTO> content = sysUserMapper.getUsers(userDTO);
        Long totalElements = Long.valueOf(sysUserMapper.getUserCount(userDTO));
        return BaseResult.success(new PageVO<>(content,totalElements));
    }

    @Override
    @Transactional
    public BaseResult delete(Set<Long> ids) {
        LambdaUpdateWrapper<SysUserRole> wrapper = new LambdaUpdateWrapper<>();
        //先删除用户角色关系
        ids.stream().forEach(uid->{
            sysUserRoleMapper.delete(wrapper.eq(SysUserRole::getUserId,uid));
        });
        //删除用户信息
        sysUserMapper.deleteBatchIds(ids);
        return BaseResult.success();
    }

    @Override
    @Transactional
    public BaseResult addUser(SysUser sysUser) {
        //密码加密
        sysUser.setPassword(passwordEncoder.encode(sysUser.getPassword()));
        sysUser.setCreateBy(UserUtils.getUser().getUsername());
        sysUser.setProductId(0);
        //添加用户信息
        try{
            if (sysUserMapper.insert(sysUser) <=0){
                return BaseResult.fail(ErrorCode.CODE_1007);
            }
        }catch (Exception e){
            return BaseResult.fail(ErrorCode.CODE_1007);
        }
        //添加用户角色信息
        if (!StrUtil.isEmptyIfStr(sysUser.getRids())){
            String[] rids = sysUser.getRids().split("[,]");
            Arrays.stream(rids).forEach(rid->{
                SysUserRole userRole = new SysUserRole();
                userRole.setUserId(sysUser.getId());
                userRole.setRoleId(Long.parseLong(rid));
                sysUserRoleMapper.insert(userRole);
            });
        }else{
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return BaseResult.fail(ErrorCode.CODE_1006);
        }
        return BaseResult.success();
    }

    @Override
    @Transactional
    public BaseResult editUser(SysUser sysUser) {
        //密码加密、添加更新人和更新时间
        if (!StrUtil.isEmptyIfStr(sysUser.getPassword())){
            sysUser.setPassword(passwordEncoder.encode(sysUser.getPassword()));
        }
        sysUser.setUpdateBy(UserUtils.getUser().getUsername());
        //更新用户信息
        if (sysUserMapper.updateById(sysUser)<=0){
            return BaseResult.fail();
        }
        //更新用户角色信息
        if (!StrUtil.isEmptyIfStr(sysUser.getRids())){
            String [] rids = sysUser.getRids().split("[,]");
            LambdaQueryWrapper<SysUserRole> wrapper = new LambdaQueryWrapper<>();
            Arrays.stream(rids).forEach(rid->{
                //要根据uid和rid一起查询是否存在
                wrapper.eq(SysUserRole::getUserId,sysUser.getId());
                wrapper.eq(SysUserRole::getRoleId,rid);
                //如果用户角色关联存在那么就不关，否则就插入
                if (sysUserRoleMapper.selectOne(wrapper) == null){
                    SysUserRole userRole = new SysUserRole();
                    userRole.setUserId(sysUser.getId());
                    userRole.setRoleId(Long.valueOf(rid));
                    sysUserRoleMapper.insert(userRole);
                }
            });
        }
        return BaseResult.success();
    }

    @Override
    public void download(HttpServletResponse response) {
        //先读取数据库中用户数据
        List<UserDTO> users = sysUserMapper.getUsers(null);

        List<Map<String, Object>> list = new ArrayList<>();

        users.forEach(user->{
            Map<String, Object> map = new HashMap<>();
            map.put("登录账号",user.getUsername());
            map.put("所属公司",user.getCompanyName());
            List<String> roles = user.getRoles().stream().map(SysRole::getName).collect(Collectors.toList());
            map.put("角色信息",roles);
            map.put("是否可用",user.getEnabled().equals("true")?"可用":"不可用");
            map.put("创建日期",user.getCreateTime());
            map.put("上次登录登录时间",user.getLastLoginTime());
            list.add(map);
        });

        //下载Excel
        try {
            FileUtil.downloadExcel(list,response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public BaseResult listConsultant(Long companyId) {
        // 获取全部
        List<AuthUser> users = sysUserMapper.listConsultant(companyId);
        return BaseResult.success(users);
    }

}
